#include "themeController.h"
#include <QDebug>
#include <QVariant>
#include <QPainter>
#include <QGuiApplication>
#include <QPainterPath>
#include <QStringList>
#include <QApplication>
#include <QtMath>

#define ColorDifference 10

static  WidgetThemeFlag g_widgetThemeFlag = DefaultTheme;
static  ThemeFlag g_themeFlag = LightTheme;
static  IconFlag g_iconFlag = ClassicStyle;
static  int g_fontSize = 11;
static  QGSettings* g_gsetting=nullptr;
QStringList applist{
//    "kylin-nm",
    "ukui-menu",
    "ukui-panel",
    "ukui-sidebar",
    "ukui-volume-control-applet-qt",
    "panelukui-panel",
    "ukui-power-manager-tray",
//    "ukui-bluetooth",
    "sogouimebs",
    "kylin-device-daemoon",
    "ukui-notifications",
    "ukui-flash-disk",
    "mktip",
    "kylin-video"
};

static inline qreal mixQreal(qreal a, qreal b, qreal bias)
{
    return a + (b - a) * bias;
}
static inline QColor adjustColor(const QColor c, int hRange = 0, int sRange = 0, int lRange = 0, int aRange = 0)
{
    QColor cc;
    int s, l, a;

    if((c.hslSaturationF() + sRange * 1.0 / 100.0) > 1){
//        qWarning() << "adjustColor s out of range1";
        s = 255;
    }
    else if((c.hslSaturationF() + sRange * 1.0 / 100.0) < 0){
//        qWarning() << "adjustColor s out of range0";
        s = 0;
    }
    else
        s = (c.hslSaturationF() + sRange * 1.0 / 100.0) *255.0;

    if((c.lightnessF() + lRange * 1.0 / 100.0) > 0.97){//根据设计稿寻光色彩识别   l应<=0.97
        qWarning() << "adjustColor l out of range1" << c.lightnessF() << lRange << (c.lightnessF() + lRange * 1.0 / 100.0);
        l = 255.0 * 0.97;
    }
    else if((c.lightnessF() + lRange * 1.0 / 100.0) < 0.15){//根据设计稿上l最小取的均值
        qWarning() << "adjustColor l out of range0";
        l = 0.15 * 255.0;
    }
    else
        l = (c.lightnessF() + lRange * 1.0 / 100.0) *255.0;

    if((c.alphaF() + aRange * 1.0 / 100.0) > 1){
        qWarning() << "adjustColor a out of range1";
        a = 255;
    }
    else if((c.alphaF() + aRange * 1.0 / 100.0) < 0){
        qWarning() << "adjustColor a out of range0";
        a = 0;
    }
    else
        a = (c.alphaF() + aRange * 1.0 / 100.0) *255.0;
    cc.setHsl(c.hslHue() + hRange, s, l, a);
    return  cc;
}

QPixmap ThemeController::drawSymbolicColoredPixmap(const QPixmap &source)
{
    QColor gray(128,128,128);
    QColor standard (31,32,34);
    QImage img = source.toImage();
    for (int x = 0; x < img.width(); x++) {
        for (int y = 0; y < img.height(); y++) {
            auto color = img.pixelColor(x, y);
            if (color.alpha() > 0) {
                if (qAbs(color.red()-gray.red())<20 && qAbs(color.green()-gray.green())<20 && qAbs(color.blue()-gray.blue())<20) {
                    color.setRed(255);
                    color.setGreen(255);
                    color.setBlue(255);
                    img.setPixelColor(x, y, color);
                }
                else if(qAbs(color.red()-standard.red())<20 && qAbs(color.green()-standard.green())<20 && qAbs(color.blue()-standard.blue())<20)
                {
                    color.setRed(255);
                    color.setGreen(255);
                    color.setBlue(255);
                    img.setPixelColor(x, y, color);
                }
                else
                {
                    img.setPixelColor(x, y, color);
                }
            }
        }
    }
    return QPixmap::fromImage(img);
}

QPixmap ThemeController::drawColoredPixmap(const QPixmap &source, const QColor &sampleColor)
{
//    QColor gray(128,128,128);
//    QColor standard (31,32,34);
    QImage img = source.toImage();
    for (int x = 0; x < img.width(); x++)
    {
        for (int y = 0; y < img.height(); y++)
        {
            auto color = img.pixelColor(x, y);
            if (color.alpha() > 0)
            {
                color.setRed(sampleColor.red());
                color.setGreen(sampleColor.green());
                color.setBlue(sampleColor.blue());
                img.setPixelColor(x, y, color);
             }
        }
    }
    return QPixmap::fromImage(img);
}

QColor ThemeController::getCurrentIconColor()
{
    QPixmap pixmap = QIcon::fromTheme("open-menu-symbolic").pixmap(16,16);
    QImage img = pixmap.toImage();
    for (int x = 0; x < img.width(); x++)
    {
        for (int y = 0; y < img.height(); y++)
        {
            auto color = img.pixelColor(x, y);
            if (color.alpha() > 0)
            {
                return color;
            }
        }
    }
}

QColor ThemeController::mixColor(const QColor &c1, const QColor &c2, qreal bias)
{
    if (bias <= 0.0) {
        return c1;
    }
    if (bias >= 1.0) {
        return c2;
    }
    if (qIsNaN(bias)) {
        return c1;
    }

    qreal r = mixQreal(c1.redF(),   c2.redF(),   bias);
    qreal g = mixQreal(c1.greenF(), c2.greenF(), bias);
    qreal b = mixQreal(c1.blueF(),  c2.blueF(),  bias);
    qreal a = mixQreal(c1.alphaF(), c2.alphaF(), bias);

    return QColor::fromRgbF(r, g, b, a);
}

WidgetThemeFlag ThemeController::widgetTheme()
{
    return g_widgetThemeFlag;
}

ThemeFlag ThemeController::themeMode()
{
    return g_themeFlag;
}

IconFlag ThemeController::iconTheme()
{
    return g_iconFlag;
}

int ThemeController::systemFontSize()
{
    if(!g_gsetting)
        return 11;
    if(g_gsetting->keys().contains("systemFontSize"))
    {
        g_fontSize = (int)g_gsetting->get("systemFontSize").toDouble();
    }
    return g_fontSize;
}

QPixmap ThemeController::drawFashionBackground(const QRect&rect,int sub_width,int sub_height,int radius, int flag)
{

//    int radius = 6;
//    int sub_width = 32;
//    int sub_height = 36;
    QPixmap framePixmap(rect.size());

    framePixmap.fill(Qt::transparent);
    QRect drawRect;
    drawRect = rect.adjusted(0, 0, 1, 1);

    auto baseColor = qApp->palette().color(QPalette::Active, QPalette::Button);

    QColor startColor = mixColor(baseColor,QColor(Qt::white),0.5);
    QColor endColor = mixColor(baseColor,QColor(Qt::black),0.1);

    QLinearGradient linearGradient;
    QPainterPath path;
    if(flag) //right
    {
        path.moveTo(drawRect.bottomRight() - QPoint(0,radius + sub_height));
        path.lineTo(drawRect.bottomRight() - QPoint(0,radius));
        path.quadTo(drawRect.bottomRight(), drawRect.bottomRight() - QPoint(radius,0));
        path.lineTo(drawRect.bottomRight() - QPoint(radius + sub_width,0));
        path.quadTo(drawRect.bottomRight(),drawRect.bottomRight() - QPoint(0,radius + sub_height));

        linearGradient.setColorAt(0, startColor);
        linearGradient.setColorAt(1, endColor);
        linearGradient.setStart(drawRect.right(), drawRect.bottom() - (radius + sub_height));
        linearGradient.setFinalStop(drawRect.right(), drawRect.bottom());
    }
    else //left
    {
        path.moveTo(drawRect.bottomLeft() - QPoint(0,radius + sub_height));
        path.lineTo(drawRect.bottomLeft() - QPoint(0,radius));
        path.quadTo(drawRect.bottomLeft(), drawRect.bottomLeft() + QPoint(radius,0));
        path.lineTo(drawRect.bottomLeft() + QPoint(radius + sub_width,0));
        path.quadTo(drawRect.bottomLeft(),drawRect.bottomLeft() - QPoint(0,radius + sub_height));

        linearGradient.setColorAt(0, startColor);
        linearGradient.setColorAt(1, endColor);
        linearGradient.setStart(drawRect.left(), drawRect.bottom() - (radius + sub_height));
        linearGradient.setFinalStop(drawRect.left(), drawRect.bottom());
    }
    QPainter painter(&framePixmap);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::transparent);
    painter.setBrush(linearGradient);
    painter.drawPath(path);
    return framePixmap;
}

bool ThemeController::isPixmapPureColor(const QPixmap &pixmap)
{
    QColor symbolic_color = QColor(38, 38, 38);

        if (pixmap.isNull()) {
            return false;
        }
        QImage image = pixmap.toImage();

        QVector<QColor> vector;
        int total_red = 0;
        int total_green = 0;
        int total_blue = 0;
        bool pure = true;
        for (int y = 0; y < image.height(); ++y) {
            for (int x = 0; x < image.width(); ++x) {
                if (image.pixelColor(x, y).alphaF() > 0.3) {
                    QColor color = image.pixelColor(x, y);
                    vector << color;
                    total_red += color.red();
                    total_green += color.green();
                    total_blue += color.blue();
                    int dr = qAbs(color.red() - symbolic_color.red());
                    int dg = qAbs(color.green() - symbolic_color.green());
                    int db = qAbs(color.blue() - symbolic_color.blue());
                    if (dr > ColorDifference || dg > ColorDifference || db > ColorDifference)
                        pure = false;
                }
            }
        }

        if (pure)
            return true;

        qreal squareRoot_red = 0;
        qreal squareRoot_green = 0;
        qreal squareRoot_blue = 0;
        qreal average_red = total_red / vector.count();
        qreal average_green = total_green / vector.count();
        qreal average_blue = total_blue / vector.count();
        for (QColor color : vector) {
            squareRoot_red += (color.red() - average_red) * (color.red() - average_red);
            squareRoot_green += (color.green() - average_green) * (color.green() - average_green);
            squareRoot_blue += (color.blue() - average_blue) * (color.blue() - average_blue);
        }

        qreal arithmeticSquareRoot_red = qSqrt(squareRoot_red / vector.count());
        qreal arithmeticSquareRoot_green = qSqrt(squareRoot_green / vector.count());
        qreal arithmeticSquareRoot_blue = qSqrt(squareRoot_blue / vector.count());
        return arithmeticSquareRoot_red < 2.0 && arithmeticSquareRoot_green < 2.0 && arithmeticSquareRoot_blue < 2.0;
}

ThemeController::ThemeController()
    :m_gsetting(nullptr)
{
    if(QGSettings::isSchemaInstalled(FITTHEMEWINDOW))
    {
        m_gsetting = new QGSettings(FITTHEMEWINDOW);
        g_gsetting = m_gsetting;
        initThemeStyle();
    }
}

ThemeController::~ThemeController()
{

}

void ThemeController::initThemeStyle()
{
    if(!m_gsetting)
        return;
    if(m_gsetting->keys().contains("styleName"))
    {
        QString styleName = m_gsetting->get("styleName").toString();
        if(styleName == "ukui-dark" || styleName == "ukui-black" || (styleName == "ukui-default" && applist.contains(QApplication::applicationName())))
            g_themeFlag = DarkTheme;
        else
            g_themeFlag = LightTheme;
    }

    //初始化图标主题
    if(m_gsetting->keys().contains("iconThemeName"))
    {
        QString iconThemeName = m_gsetting->get("iconThemeName").toString();
        if(iconThemeName == "ukui-icon-theme-default")
            g_iconFlag = DefaultStyle;
        else
        {
            g_iconFlag = ClassicStyle;
        }
    }
    if(m_gsetting->keys().contains("widgetThemeName"))
    {
        //初始化样式主题
        QString widgetThemeName = m_gsetting->get("widgetThemeName").toString();
        if(widgetThemeName == "default")
            g_widgetThemeFlag = DefaultTheme;
        else if(widgetThemeName == "classical")
            g_widgetThemeFlag = ClassicTheme;
        else
           g_widgetThemeFlag = FashionTheme;
    }
}
